package com.laen.demo.task;

import java.io.IOException;

import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.internal.io.ResourceFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

/**
 * 乘务员数据处理定时任务抽象类
 * 
 * @author liuhuixi
 *
 * @param <T>
 * @param <R>
 */
public abstract class DroolsTask<T, R> extends AbstractCwyTask<T, R> {
    private static final String RULE_PATH = "templates/";
    protected KieSession kieSession;

    @Override
    protected void prepare() {
        kieSession = kieContainer().newKieSession();
    }

    private KieContainer kieContainer() {
        KieServices service = KieServices.Factory.get();
        final KieRepository kieRepository = service.getRepository();
        kieRepository.addKieModule(() -> kieRepository.getDefaultReleaseId());
        KieBuilder kieBuilder = service.newKieBuilder(kieFileSystem(service));
        kieBuilder.buildAll();
        return service.newKieContainer(kieRepository.getDefaultReleaseId());
    }

    private KieFileSystem kieFileSystem(KieServices service) {
        KieFileSystem kieFileSystem = service.newKieFileSystem();
        try {
            for (Resource resource : getRuleFiles()) {
                kieFileSystem.write(
                    ResourceFactory.newClassPathResource(RULE_PATH + getRuleDir() + resource.getFilename(), "UTF-8"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return kieFileSystem;
    }

    private Resource[] getRuleFiles() throws IOException {
        String drldir = getRuleDir();
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        return resourcePatternResolver.getResources("classpath:" + RULE_PATH + drldir + "**/**");
    }

    protected String getRuleDir() {
        return "";
    }

    public enum ScoreLevel {
        /**
         * A等级
         */
        A,
        /**
         * B等级
         */
        B,
        /**
         * C等级
         */
        C,
        /**
         * D等级
         */
        D;
    }

    public static class CwyFact {
        private FactHandle personFactHandle;
        private FactHandle resultFactHandle;
        private Person person;
        private Result result;
    }

    public static class Person {
        private Long gh;
        private Boolean absent;
        private Float absentDays = 0F;
        private Float workDays = 0F;

        public Person(Long gh) {
            this.gh = gh;
        }

        public Long getGh() {
            return gh;
        }

        public void setGh(Long gh) {
            this.gh = gh;
        }

        public Boolean getAbsent() {
            return absent;
        }

        public void setAbsent(Boolean absent) {
            this.absent = absent;
        }

        public Float getAbsentDays() {
            return absentDays;
        }

        public void setAbsentDays(Float absentDays) {
            this.absentDays = absentDays;
        }

        public Float getWorkDays() {
            return workDays;
        }

        public void setWorkDays(Float workDays) {
            this.workDays = workDays;
        }
    }

    public static class Result {
        private Integer countOfContinuousAbsent;
        private Long gh;
        private Integer score = 100;
        private ScoreLevel scoreLevel = ScoreLevel.A;

        public Result(Long gh) {
            this.gh = gh;
        }

        public Integer getCountOfContinuousAbsent() {
            return countOfContinuousAbsent;
        }

        public void setCountOfContinuousAbsent(Integer countOfContinuousAbsent) {
            this.countOfContinuousAbsent = countOfContinuousAbsent;
        }

        public Long getGh() {
            return gh;
        }

        public void setGh(Long gh) {
            this.gh = gh;
        }

        public Integer getScore() {
            return score;
        }

        public void setScore(Integer score) {
            this.score = score;
        }

        public ScoreLevel getScoreLevel() {
            return scoreLevel;
        }

        public void setScoreLevel(ScoreLevel scoreLevel) {
            this.scoreLevel = scoreLevel;
        }
    }

    private class CwyAbsentStatus {
        private Long gh;
        private Boolean absent;
        private Boolean workday;

        public CwyAbsentStatus(Long gh, boolean absent, boolean workday) {
            this.gh = gh;
            this.absent = absent;
            this.workday = workday;
        }

        public Long getGh() {
            return gh;
        }

        public CwyAbsentStatus setGh(Long gh) {
            this.gh = gh;
            return this;
        }

        public Boolean getAbsent() {
            return absent;
        }

        public CwyAbsentStatus setAbsent(Boolean absent) {
            this.absent = absent;
            return this;
        }

        public Boolean getWorkday() {
            return workday;
        }

        public CwyAbsentStatus setWorkDay(Boolean workday) {
            this.workday = workday;
            return this;
        }
    }
}
